package com.example.tetris.gui;

import com.example.tetris.App;
import com.example.tetris.logics.components.CellList;
import com.example.tetris.logics.components.ScoreInfo;
import com.example.tetris.logics.controller.GameManager;
import com.example.tetris.logics.event.Event;
import com.example.tetris.restore.GameSave;
import javafx.animation.KeyFrame;
import javafx.animation.ScaleTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;

import java.io.IOException;

public class GamePageController {
    private static final int BRICK_SIZE = 20;
    @FXML public Group notificationGroup;
    @FXML private GridPane nextBrickGridPane;
    @FXML private VBox root;
    @FXML private GridPane gridPane;

    public Pane getGameWindowPane() {
        return gameWindowPane;
    }

    @FXML private Pane gameWindowPane;
    @FXML private ToggleButton btPause;
    public static final int rows = 20;//还有看不见的2行,实际显示的是18行
    public static final int cols = 10;
    private Rectangle[][] blocks;
    private Rectangle[][] nextBrickBlocks;
    private final BooleanProperty isPause = new SimpleBooleanProperty();

    private boolean start = false;
    private GameManager gameManager;

    private Timeline timeline;
    @FXML private BorderPane gameOverPanel;
    @FXML Label score;
    @FXML Label grade;
    private  boolean isPaused = false;
    private final BooleanProperty isGameOver = new SimpleBooleanProperty(false);

    public void gameOver() {
        timeline.stop();
        isGameOver.setValue(Boolean.TRUE);

    }
    @FXML
    public void initialize() {

        gameManager = new GameManager(this);//让gui部分与逻辑控制部分相互关联

         blocks = new Rectangle[rows - 2][cols];
         nextBrickBlocks = new Rectangle[2][4];

        for (int row = 0; row < rows - 2; row++) {
            for (int col = 0; col < cols; col++) {
                Rectangle block = new Rectangle(BRICK_SIZE,BRICK_SIZE);
                block.getStyleClass().add("block-empty");
                blocks[row][col] = block;
                gridPane.add(block, col, row);
            }
        }
        for (int row = 0; row < 2; row++) {
            for (int col = 0; col < 4; col++) {
                Rectangle block = new Rectangle(BRICK_SIZE,BRICK_SIZE);
                block.getStyleClass().add("block-empty");
                nextBrickBlocks[row][col] = block;
                nextBrickGridPane.add(block, col, row);

            }
        }

        gameWindowPane.setFocusTraversable(true);
        gameWindowPane.setOnKeyPressed(this::handleKeyPress);
        gameWindowPane.requestFocus();


        btPause.selectedProperty().bindBidirectional(isPause);
        btPause.selectedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if(isGameOver.getValue()){
                    gameWindowPane.requestFocus();
                    return;
                }
                if (newValue) {
                    timeline.pause();
                    btPause.setText("|>");
                    isPaused = true;
                } else {
                    timeline.play();
                    btPause.setText("||");
                    isPaused = false;
                }
                gameWindowPane.requestFocus();

            }
        });

        isGameOver.setValue(false);
        gameOverPanel.visibleProperty().bind(isGameOver);
    }

    private void handleKeyPress(KeyEvent keyEvent) {
        switch (keyEvent.getCode()){
            case W: case UP:setOnRotateButtonClicked();
                keyEvent.consume();break;
            case A: case LEFT:setOnLeftButtonClicked();
                keyEvent.consume();break;
            case S: case DOWN:setOnDownButtonClicked();
                keyEvent.consume();break;
            case D: case RIGHT:setOnRightButtonClicked();
                keyEvent.consume();break;
            case P:GameSave.saveGame(gameManager);
                keyEvent.consume();break;
            case SPACE:setOnFallButtonClicked();
                keyEvent.consume();break;
        }
    }

    public void paintBoard(){
        CellList cellsToPaint = gameManager.getViewData().getGameWindowDataCells();
        for (int y = 2; y < rows; y++) {
            for (int x = 0; x < cols; x++) {
                blocks[y-2][x].getStyleClass().clear();
                if(cellsToPaint.getCellAt(x,y) != null){
                    blocks[y-2][x].getStyleClass().add("block-filled");

                }else{
                    blocks[y-2][x].getStyleClass().add("block-empty");
                }
            }
        }

        CellList cellsNextBrick = gameManager.getViewData().getNextBrickDataCells();
        for (int y = 0; y < 2; y++) {
            for (int x = 0; x < 4; x++) {
                nextBrickBlocks[y][x].getStyleClass().clear();
                if(cellsNextBrick.getCellAt(x,y + 1) != null){
                    nextBrickBlocks[y][x].getStyleClass().add("block-filled");

                }else{
                    nextBrickBlocks[y][x].getStyleClass().add("block-empty");
                }

            }
        }

        ScoreInfo scoreInfo = gameManager.getViewData().getScoreInfo();
        int nextScore = scoreInfo.getscore();
        int nextGrade = scoreInfo.getGrade();
        int currentScore = Integer.parseInt(score.getText());
        int currentGrade = Integer.parseInt(grade.getText());

        if(nextScore != currentScore){
            score.setText(String.valueOf(nextScore));
            AnimationGenerator.scaleLabel(score,1.5);

        }
        if(nextGrade != currentGrade){
            grade.setText(String.valueOf(nextGrade));
            AnimationGenerator.scaleLabel(grade,2);
        }

    }



    public void setOnMusicButtonClicked(ActionEvent actionEvent) {
        gameWindowPane.requestFocus();
        //TODO
    }

    public void setOnRestartButtonClicked() throws IOException {
        gameWindowPane.requestFocus();
        App.setRoot("gamePage");

        //TODO
    }

    public void setOnFallButtonClicked() {
        gameWindowPane.requestFocus();
        if(isGameOver.getValue() || isPaused){
            return;
        }
        if(!start){//fall键还有开启游戏的作用
            start = !start;
            timeline = new Timeline(new KeyFrame(Duration.millis(400), event ->{
                gameManager.onDownEvent(Event.THREAD);
            } ));
            timeline.setCycleCount(Timeline.INDEFINITE);
            timeline.play();
            Timeline timelineGameSave = new Timeline(new KeyFrame(Duration.millis(1000),event -> {//每隔1s存档
                GameSave.saveGame(gameManager);
            }));
            timelineGameSave.setCycleCount(Timeline.INDEFINITE);
            timelineGameSave.play();
        }else{//已经开始，掉落效果
            gameManager.onFallEvent();
        }
    }

    public void setOnRotateButtonClicked() {
        gameWindowPane.requestFocus();
        if(!start){
            return;
        }
        if(isGameOver.getValue() || isPaused){
            return;
        }
        gameManager.onRotateEvent();
        //TODO
    }

    public void setOnLeftButtonClicked() {
        gameWindowPane.requestFocus();
        if(!start){
            return;
        }
        if(isGameOver.getValue() || isPaused){
            return;
        }
        gameManager.onLeftEvent();
        //TODO
    }

    public void setOnRightButtonClicked() {
        gameWindowPane.requestFocus();
        if(!start){
            return;
        }
        if(isGameOver.getValue() || isPaused){
            return;
        }
        gameManager.onRigntEvent();
        //TODO
    }

    public void setOnDownButtonClicked() {
        gameWindowPane.requestFocus();
        if(!start){
            return;
        }
        if(isGameOver.getValue() || isPaused){
            return;
        }
        gameManager.onDownEvent(Event.USER);
        //TODO
    }

    public Timeline delRowAnimation(int... rowIndexes){
        return AnimationGenerator.blinkLineAnimation(timeline,blocks,rowIndexes);
    }

    public void closeSystem(){
        Platform.exit();
        System.exit(0);
    }
    public void minimizeWindow(){
        App.getStage().setIconified(true);
        gameWindowPane.requestFocus();

    }
    public  void setGameManager(GameManager gameManager){
        this.gameManager = gameManager;
    }


    public void backHome(ActionEvent actionEvent) throws IOException {
        App.setRoot("home");
    }

    public void addScoreAnimation(int score){
        NotificationPanel notificationPanel = new NotificationPanel("+ " + score);
        notificationGroup.getChildren().add(notificationPanel);
        notificationPanel.showScore(notificationGroup.getChildren());

    }
}
